#!/usr/bin/env python

import sys
import os
import getopt
import csv
import xml.etree.ElementTree as ET

# -*- coding: utf-8 -*-
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

#  1,读取矩阵文件，找出对应开发板的所不需要的组件，输出一个列表A
#  2,读取default.xml文件，确认不需要的库，字典模式:name:path
#  3,根据字典库的name,组装为新的xml文件(remove-project标签)。
#  defines for some error for the csv says N but the product really need it
PATCH_LITE_M = ["prebuilts_lite_sysroot", "third_party_cmsis", "third_party_littlefs"]
PATCH_LITE_A = []
PATCH_LINUX_L1 = []
PATCH_LINUX_L2 = []
PATCH_SELECT = PATCH_LITE_M
REPO_PATH = '.'
PRODUCT_NAME = 'hispark_pegasus'
PRODUCT_LIST = []
CSV_FILE = "manifests/matrix_product.csv"
XML_FILE = "manifests/default.xml"
LOCAL_MANIFESTS = "local_manifests"
LOCAL_MANIFESTS_FILE = "local_manifests/default.xml"
TOOL_VERSION = "0.0.1"


def set_patch(kernel_type='lite-m'):
    global PATCH_SELECT
    if kernel_type == 'lite-m':
        PATCH_SELECT = PATCH_LITE_M
    elif kernel_type == 'lite-a':
        PATCH_SELECT = PATCH_LITE_A
    elif kernel_type == "linux-l1":
        PATCH_SELECT = PATCH_LINUX_L1
    elif kernel_type == "linux-l2":
        PATCH_SELECT = PATCH_LINUX_L2
    else:
        print("You could only select:lite-m lite-a linux-l1 linux-l2")
        return False
    return True


def set_repo_path(repo_path=''):
    global REPO_PATH
    global XML_FILE
    global CSV_FILE
    global LOCAL_MANIFESTS
    global LOCAL_MANIFESTS_FILE
    REPO_PATH = repo_path
    CSV_FILE = os.path.join(REPO_PATH, CSV_FILE)
    XML_FILE = os.path.join(REPO_PATH, XML_FILE)
    LOCAL_MANIFESTS = os.path.join(REPO_PATH, LOCAL_MANIFESTS)
    LOCAL_MANIFESTS_FILE = os.path.join(REPO_PATH, LOCAL_MANIFESTS_FILE)

    if not ((os.path.exists(CSV_FILE) and os.path.isfile(CSV_FILE) and
            os.path.exists(XML_FILE) and os.path.isfile(XML_FILE))):
        print(f"{CSV_FILE} or {XML_FILE} missing")
        return False
    else:
        os.makedirs(name=LOCAL_MANIFESTS, exist_ok=True)
        return True


def list_product() -> bool:
    render_rows = []
    global PRODUCT_LIST
    with open(CSV_FILE) as f:
        render = csv.reader(f)
        render_rows = [row for row in render]
    if len(render_rows) <= 1:
        print(f"{CSV_FILE} in wrong format")
        return False
    header = render_rows[0]
    PRODUCT_LIST = header[2:]
    return True


def get_unnecessary_component():
    """
    :return: the not must component list for the vendor_product
    """
    # some resposity must be needed ,but say N in csv file, so we must filter these
    components_unnecessary_list = []
    render_rows = []
    with open(CSV_FILE) as f:
        render = csv.reader(f)
        render_rows = [row for row in render]
    if (not render_rows) or (len(render_rows) <= 1):
        return components_unnecessary_list
    vendor_product_list = render_rows[0]
    components_list = render_rows[1:]
    if PRODUCT_NAME not in vendor_product_list:
        return components_unnecessary_list

    # here we begin to match the "N" value and add it to the list
    vendor_product_column = vendor_product_list.index(PRODUCT_NAME)
    for component in components_list:
        if component[0] in PATCH_SELECT:
            continue
        if component[vendor_product_column] == "N":
            components_unnecessary_list.append(component[0])
    return components_unnecessary_list


def get_unnecessary_component_path(unnecessary_components=None):
    """
    :return: the dict{name:path} for the invalid component list
    """
    if unnecessary_components is None:
        unnecessary_components = ["kernel_xxx"]
    projects = {}
    tree = ET.parse(XML_FILE)
    root = tree.getroot()
    items = root.findall("project")
    for item in items:
        attrib_dict = item.attrib
        name_value = attrib_dict["name"]
        path_value = attrib_dict["path"]
        if name_value in unnecessary_components:
            projects[name_value] = path_value
            root.remove(item)
    return projects

# This is the local_manifests/default.xml content template
# """
# <?xml version="1.0" encoding="UTF-8"?>
# <manifest>
#   <remote fetch="https://gitee.com/Cruise2019/" name="team_x" />
#   <project name="team_x_boards" path="device/team_x_boards" remote="team_x" revision="master"/>
#   <project name="team_x_products" path="vendor/team_x_products" remote="team_x" revision="master" />
#   <remove-project name="platform/external/mesa3d"/>
# </manifest>
# """


def add_sub_element(root, tag, attrib):
    """
    :param root: the root element
    :param tag: the element tag
    :param attrib: the element attrib
    :return: No return needed
    """
    new_element = ET.SubElement(root, tag)
    new_element.attrib["name"] = attrib
    new_element.tail = '\n'

def make_xml(projects=None):
    """
    :param projects: This is the projects to be removed
    :return:
    """
    if projects is None:
        projects = {}
    root = ET.Element("manifest")
    project_paths = projects.keys()
    for project_path in project_paths:
        add_sub_element(root, "remove-project", project_path)
    tree = ET.ElementTree(root)
    tree.write(LOCAL_MANIFESTS_FILE, encoding="utf-8", xml_declaration=True)


def tool_usage():
    """
    :return: No return needed
    """
    text = f"""   
    This is repo cutting for OpenHarmony,{TOOL_VERSION}  
    Usage:python repo_cutting.py [-d repo_dir] [-v] [-h] [-p product_name] [-k kernel_level]
          repo_dir default for '.'
          product_name default for 'hispark_pegasus'
          kernel_level default for 'lite-m', and could be set as lite-m lite-a linux-l1 linux-l2
    """
    print(text)


def main() -> None:
    unnecessary_components = get_unnecessary_component()
    # make sure the remove-projects exist in the default/xml file
    remove_projects = get_unnecessary_component_path(unnecessary_components)
    # print(remove_projects)
    make_xml(remove_projects)


if __name__ == "__main__":
    args_format, args_unformat = getopt.getopt(sys.argv[1:], '-h-v-d:-l-p:')
    # print(args_format)
    m = dict(args_format)

    if '-v' in m:
        print(f"{TOOL_VERSION}")
        sys.exit()

    if '-h' in m:
        tool_usage()
        sys.exit()

    if '-d' in m:
        if not set_repo_path(m['-d']):
            sys.exit()
    else:
        if not set_repo_path(REPO_PATH):
            sys.exit()

    if not list_product():
        sys.exit()

    if '-l' in m:
        print(PRODUCT_LIST)
        sys.exit()

    if '-p' in m:
        if m['-p'] not in PRODUCT_LIST:
            print(f"{m['-p']} not in {PRODUCT_LIST}")
            sys.exit()
        else:
            PRODUCT_NAME = m['-p']

    if '-k' in m:
        if not set_patch(m['-k']):
            sys.exit()

    main()
